home *** CD-ROM | disk | FTP | other *** search
/ BBS in a Box 3 / BBS in a box - Trilogy III.iso / Files / Tele / C / Comet2.1.3 Folder / Comet / vt100.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-07-02  |  30.5 KB  |  1,421 lines  |  [TEXT/dumv]

  1. /*
  2.     Copyright Cornell University 1988.  All rights are reserved.
  3. */
  4.  
  5. #include    <em.h>
  6.  
  7. #include    <h19.h>
  8. #include    <macdefs.h>
  9. #include    <rcodes.h>
  10.  
  11. /* globals */
  12. char vt100AVOid[] = "\033[?1;2c";    /* response to whoami request */
  13. char vt102id[] = "\033[?6c";    /* response to whoami request */
  14. char vt220id[] = "\033[?62;1;2c";    /* response to whoami request, level 2
  15.                                     with 7-bit controls & printer port */
  16.  
  17. char imokstr[] = "\033[0n";        
  18.  
  19. extern int (*screen_upd)();
  20.  
  21. extern short usedsdraw;            /* set through emprep() */
  22. extern short emupdwait;            /* set through emprep() */
  23.  
  24. /* make an array for mapping special VT chars into our font... */
  25.  
  26. #ifdef MERGEDVTCHARS
  27.  
  28. unsigned char vtfontmap[32] = {
  29.     130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145,
  30.     146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 196, 185, 197, 0
  31. };
  32.  
  33. #define FIRSTVTSYM     96        /* first special font symbol of 31 such... */
  34. #define LASTVTSYM    126
  35.  
  36. #endif
  37.  
  38. /* character at a time interface */
  39.  
  40. vt100(thechar)
  41. char thechar;
  42. {
  43.     vt100str(&thechar, 1);
  44. }
  45.  
  46.  
  47. /* string interface */
  48.  
  49. vt100str(strp, ccount)
  50. register unsigned char * strp;
  51. short ccount;
  52. {
  53.     register unsigned char * endp = strp + ccount;
  54.     register unsigned char thechar;
  55.     register short thearg;
  56.     short count;
  57.     
  58.     emprep();
  59.     if (usedsdraw) {
  60.         emdp->inselection = chkinvert();
  61.         setascattr_ds(attrib, emdp->inselection);
  62.  
  63.     }
  64.     
  65.     while (strp < endp) {
  66.         thechar = *strp++;                 /* we assume high bit off... */
  67.         if (vtmode == NORMMODE) {
  68.             /* NORMMODE interpreted here to avoid switch overhead */
  69.             /* draw character if alphanumeric */
  70.             if (emdp->emliteral || (thechar >= 0x20 && thechar != 0x7f)) {
  71.                 if (emdp->wrapped) {
  72.                     /* do the scroll we delayed earlier */
  73.                     wrapdown();
  74.                 }
  75. #ifdef BETTERLITERAL
  76.                 if (emdp->emliteral) {
  77.                     /* remap control chars so they are not interpreted */
  78.                     if (thechar == CR) {
  79.                         thechar = 0x86;
  80.                     }
  81.                     else if (thechar == HTAB) {
  82.                         thechar = 0x84;
  83.                     }
  84.                 }
  85. #endif
  86.                 if (inserton) {
  87.                     ins_char();
  88.                 }
  89. #ifdef MERGEDVTCHARS
  90.                 if (emdp->charset) {
  91.                     /* vt font in effect */
  92.                     if (thechar >= FIRSTVTSYM && thechar <= LASTVTSYM) {
  93.                         /* it's a special char, remap, otherwise leave it be */
  94.                         thechar = vtfontmap[thechar - FIRSTVTSYM];
  95.                     }
  96.                 }
  97. #endif
  98.                 *charp = thechar;
  99.                 *(charp + emdp->screensize) = attrib;
  100.                 if (emdp->matchinput) {
  101.                     /* we're trying to match input characters */
  102.                     if (matchtoken(thechar))
  103.                         resumetokens(emdp); 
  104.                 }
  105. #ifdef FASTDRAW
  106.                 if (usedsdraw && !modflg) {
  107.                     /* we're using direct-to-screen drawing; if 
  108.                         some QD has been used (e.g. jumpscroll) keep on using it */
  109. #ifdef NOMODFLGTEST
  110.                     /* if there's no !modflg test above, we need this... */
  111.                     if (modflg) {
  112.                         emrefresh(emwindow, TRUE);
  113.                     }    
  114. #endif
  115.                     if (emdp->selrectvis) {
  116.                         if (emdp->inselection != chkinvert()) {
  117.                             if (emdp->inselection)
  118.                                 emdp->inselection = FALSE;
  119.                             else
  120.                                 emdp->inselection = TRUE;
  121.                             setascattr_ds(attrib, emdp->inselection);
  122.                         }
  123.                     }
  124.                     zapchar(thechar);
  125.                     clrflg &= ~modmask[ypos];        /* reset clear flag */
  126.                 }
  127.                 else {
  128.                     /* for quickdraw, draw when finished updating map
  129.                         if (inserton || count == 1)
  130.                             ch_draw_qd(thechar);
  131.                         else
  132.                      */
  133.                     modflg |= modmask[ypos];
  134.                 }
  135. #else
  136.                 modflg |= modmask[ypos];
  137. #endif
  138.     
  139.                 /* adjust cursor position */
  140.                 if (xpos < lastcol) {
  141.                     xpos++;
  142.                     charp++;
  143.                 }
  144.                 else if (wrap_around) {
  145.                     emdp->wrapped = TRUE;
  146.                     /* wait to scroll up until next char received */
  147.                 }
  148.                 continue;
  149.             }
  150.             /* else if an ascii control character... */
  151.             switch (thechar) {
  152.                 case 0x07: {
  153.                     /* BELL */
  154.                     if (!emdp->emdisable)
  155.                         beep();
  156.                     break;
  157.                 }
  158.                 case 0x08: {
  159.                     /* BS */
  160.                     if (emdp->wrapped)
  161.                         wrapdown();
  162.                     if (xpos > 0) {
  163.                         --xpos;
  164.                         --charp;
  165.                     }
  166.                     break;
  167.                 }
  168.                 case 0x09: {
  169.                     /* HTAB */
  170.                     vttab();
  171.                     break;
  172.                 }
  173.                 case 0x0d: {
  174.                     /* CR */
  175.                     emdp->wrapped = FALSE;
  176.                     charp -= xpos;
  177.                     xpos = 0;
  178.                     break;
  179.                 }
  180.                 case 0x0a:
  181.                 case 0x0b:
  182.                 case 0x0c: {
  183.                     /* LF */
  184.                     if (emdp->vtnewline) {
  185.                         /* do a CR if in newline mode */
  186.                         charp -= xpos;
  187.                         xpos = 0;
  188.                         emdp->wrapped = FALSE;
  189.                     }
  190.                     if (emdp->wrapped) {
  191.                         wrapdown();
  192.                     }
  193.                     else {
  194.                         if (ypos < emdp->scrollbottom) {
  195.                             charp += linelength;
  196.                             ypos++;
  197.                         }
  198.                         else {
  199.                             if (emdp->scrolltop == TOPROW 
  200.                                     && emdp->scrollbottom == emdp->lastrow) {
  201.                                 (*emdp->scrollup)();
  202.                             }
  203.                             else
  204.                                 del_lin(emdp->scrolltop);
  205.                         }
  206.                     }
  207.                     break;
  208.                 }
  209.                 case 0x0e: {
  210.                     /* SO, shift out G0 character set (select G1) */
  211.                     vtcharshift(TRUE);
  212.                     break;
  213.                 }
  214.                 case 0x0f: {
  215.                     /* SI, shift in G0 character set */
  216.                     vtcharshift(FALSE);
  217.                     break;
  218.                 }
  219.                 case 0x1b: {
  220.                     /* ESC */
  221.                     vtmode = VT_ESC;
  222.                     break;
  223.                 }
  224.                 case X_OFF: {
  225.                     break;
  226.                 }
  227.                 case X_ON: {
  228.                     break;
  229.                 }
  230.             }
  231. #ifdef TESTBOUND
  232.             testbound();
  233. #endif
  234.             continue;
  235.         }
  236.         /* else interpret character according to proper mode */
  237.         switch (vtmode) {
  238.             /* do nothing for NORMMODE; interpreted above the switch */
  239.             case VT_ESC: {
  240.                 vtmode = NORMMODE;
  241.                 switch (thechar) {
  242.                     case ESC: {
  243.                         /* 2 Escape characters: go into c19 file transfer mode */
  244.                         vtmode = CFTMODE;
  245.                         break;
  246.                     }
  247.                     case '[': {
  248.                         /* standard ANSI command */
  249.                         vtmode = VT_ANSI;
  250.                         if (emdp->argcount) {
  251.                             while (emdp->argcount)
  252.                                 /* clear the old entries */
  253.                                 emdp->argarr[emdp->argcount--] = 0;
  254.                         }
  255.                         emdp->argarr[0] = 0;
  256.                         argp = &emdp->argarr[0];
  257.                         break;
  258.                     }
  259.                     case '#': {
  260.                         /* interpret DEC private mode */
  261.                         vtmode = VT_POUND;
  262.                         break;
  263.                     }
  264.                     case '(': {
  265.                         vtmode = VT_LPAREN;
  266.                         break;
  267.                     }
  268.                     case ')': {
  269.                         vtmode = VT_RPAREN;
  270.                         break;
  271.                     }
  272.                     case ' ': {
  273.                         vtmode = VT_SPACE;
  274.                         break;
  275.                     }
  276.                     case 'E': {
  277.                         /* next line, do a CR Index */
  278.                         emdp->wrapped = FALSE;
  279.                         charp -= xpos;
  280.                         xpos = 0;
  281.                     }
  282.                     case 'D': {
  283.                         /* index */
  284.                         if (emdp->wrapped)
  285.                             wrapdown();
  286.                         if (ypos < emdp->scrollbottom) {
  287.                             ypos++;
  288.                             charp += linelength;
  289.                         }
  290.                         else {
  291.                             if (emdp->scrolltop == TOPROW 
  292.                                     && emdp->scrollbottom == emdp->lastrow) {
  293.                                     
  294.                                 (*emdp->scrollup)();
  295.                             }
  296.                             else
  297.                                 del_lin(emdp->scrolltop);
  298.                         }
  299.                         break;
  300.                     }
  301.                     case 'M': { 
  302.                         /*  reverse index */
  303.                         if (emdp->wrapped)
  304.                             wrapdown();
  305.                         if (ypos == emdp->scrolltop) 
  306.                             ins_lin(emdp->scrolltop);
  307.                         else if (ypos > 0) {
  308.                             --ypos;
  309.                             charp -= linelength;
  310.                         }
  311.                         break;
  312.                     }
  313.                     case '7': {
  314.                         /* save cursor position */
  315.                         emdp->ocharset = emdp->charset;
  316.                         emdp->oattrib = attrib;
  317.                         emdp->oxpos = xpos; 
  318.                         emdp->oypos = ypos;
  319.                         
  320.                         emdp->ocharsetSO = emdp->charsetSO;
  321.                         emdp->owrapped = emdp->wrapped;
  322.                         emdp->odecom = emdp->decom;
  323.                         /* vt220 also selective erase mode */
  324.                         break;
  325.                     }
  326.                     case '8': {
  327.                         /* restore cursor position */
  328.                         emdp->charset = emdp->ocharset;
  329.                         attrib = emdp->oattrib;
  330.                         xpos = emdp->oxpos; 
  331.                         ypos = emdp->oypos;
  332.                         charp = emdp->charr + xpos + (ypos * linelength);
  333.  
  334.                         emdp->wrapped = emdp->owrapped;
  335.                         emdp->decom = emdp->odecom;
  336.                         emdp->charsetSO = emdp->ocharsetSO;
  337.                         emdp->inselection = chkinvert();
  338. #ifdef FASTDRAW
  339.                         setascattr_ds(attrib, emdp->inselection);
  340. #endif
  341.                         break;
  342.                     }
  343.                     case 'H': {
  344.                         /* set tab stop at cursor */
  345.                         emdp->tabset[xpos] = TRUE;
  346.                         break;
  347.                     }
  348.                     case '=': {
  349.                         /* enter alt keypad mode */
  350.                         if (!emdp->vtkeypad)
  351.                             emdp->vtaltkeypad = TRUE;
  352.                         break;
  353.                     }
  354.                     case '>': {
  355.                         /* exit alt keypad mode */
  356.                         if (!emdp->vtkeypad)
  357.                             emdp->vtaltkeypad = FALSE;
  358.                         break;
  359.                     }
  360.                     case 'c': {
  361.                         /* Reset to Initial state */
  362.                         vt100reset();
  363. #ifdef FASTDRAW
  364.                         setascattr_ds(attrib, emdp->inselection);
  365. #endif
  366.                         break;
  367.                     }
  368.                 }
  369. #ifdef TESTBOUND
  370.                 testbound();
  371. #endif
  372.                 break;
  373.             }
  374.             case VT_ANSI: {
  375.                 short    index;
  376.  
  377.                 if ( (thechar >= '0') && (thechar <= '9') ) {
  378.                     /* another numeric arg char */
  379.                     *argp = (*argp * 10) + (thechar - '0');
  380.                     break;
  381.                 }
  382.                 if (thechar == ';') {
  383.                     if (emdp->argcount < MAXARGS) {
  384.                         argp++;
  385.                         emdp->argcount++;
  386.                     }
  387.                     break;
  388.                 }
  389.                 if (thechar < ' ') {
  390.                     /* an ASCII control char which needs to be interpreted */
  391.                     vtcontrol(thechar);
  392.                     break;
  393.                 }
  394.                 if (thechar == '?') {
  395.                     /* DEC private mode, ignore any args */
  396.                     if (emdp->argcount) {
  397.                         while (emdp->argcount)
  398.                             emdp->argarr[emdp->argcount--] = 0;
  399.                     }
  400.                     emdp->argarr[0] = 0;
  401.                     argp = &emdp->argarr[0];
  402.                     vtmode = VT_QMARK;
  403.                     break;
  404.                 }
  405.                 emdp->argcount++;
  406.                 vtmode = NORMMODE;
  407.                 thearg = emdp->argarr[0];        /* current arg, default for CUP etc. */
  408.                 
  409.                 switch (thechar) {
  410.                     case 'A': { 
  411.                         /* cursor up */
  412.                         if (thearg == 0) 
  413.                             thearg = 1;
  414. #ifdef CURMOWRAP                            
  415.                         if (emdp->wrapped)
  416.                             wrapdown();
  417. #endif
  418.                         /* TODO should scrolltop references check for decom? */
  419.                         if (thearg > ypos - emdp->scrolltop) 
  420.                             thearg = ypos - emdp->scrolltop;
  421.                         if (thearg <= 0)
  422.                             break;
  423.                             
  424.                         ypos -= thearg;
  425.                         charp -= thearg * linelength;
  426.                         break;
  427.                     }
  428.                     case 'B': { 
  429.                         /* cursor down */
  430.                         if (thearg == 0) 
  431.                             thearg = 1;
  432. #ifdef CURMOWRAP                            
  433.                         if (emdp->wrapped)
  434.                             wrapdown();
  435. #endif
  436.                         if (ypos + thearg > emdp->scrollbottom) 
  437.                             thearg = emdp->scrollbottom - ypos;
  438.                         if (thearg <= 0)
  439.                             break;
  440.                             
  441.                         ypos += thearg;
  442.                         charp += thearg * linelength;
  443.                         break;
  444.                     }
  445.                     case 'C': { 
  446.                         /* cursor right */
  447.                         if (thearg == 0) 
  448.                             thearg = 1;
  449. #ifdef CURMOWRAP                            
  450.                         if (emdp->wrapped)
  451.                             wrapdown();
  452. #endif
  453.                         if (xpos + thearg > lastcol) 
  454.                             thearg = lastcol - xpos;
  455.                         if (thearg <= 0)
  456.                             break;
  457.                             
  458.                         xpos += thearg;
  459.                         charp += thearg;
  460.                         break;
  461.                     }
  462.                     case 'D': { 
  463.                         /* cursor left */
  464.                         if (thearg == 0) 
  465.                             thearg = 1;
  466. #ifdef CURMOWRAP                            
  467.                         if (emdp->wrapped)
  468.                             wrapdown();
  469. #else
  470.                         emdp->wrapped = FALSE;
  471. #endif
  472.                         if (thearg > xpos) 
  473.                             thearg = xpos;
  474.                             
  475.                         xpos -= thearg;
  476.                         charp -= thearg;
  477.                         break;
  478.                     }
  479.                     case 'g': {
  480.                         /* clear tab(s) */
  481.                         if (thearg == 0) {
  482.                             emdp->tabset[xpos] = FALSE;
  483.                         }
  484.                         else if (thearg == 3) {
  485.                             /* clear all tabs */
  486.                             for (count = 0; count < linelength; ) {
  487.                                 emdp->tabset[count++] = FALSE;
  488.                             }
  489.                         }
  490.                         break;
  491.                     }
  492.                     case 'H':
  493.                     case 'f': { 
  494.                         /* move cursor */
  495.                         /* set the y position first */
  496.                         emdp->wrapped = FALSE;
  497.  
  498.                         if (thearg)
  499.                             --thearg;
  500.     
  501.                         if (emdp->decom) {
  502.                             /* in origin mode, correct the argument */
  503.                             thearg += emdp->scrolltop;
  504.                             if (thearg < emdp->scrolltop)
  505.                                 /* keep within top margin */
  506.                                 thearg = emdp->scrolltop;
  507.                             else if (thearg > emdp->scrollbottom)
  508.                                 /* keep within bottom margin */
  509.                                 thearg = emdp->scrollbottom;
  510.                         }
  511.                         else {
  512.                             if (thearg < 0)
  513.                                 /* keep within top margin */
  514.                                 thearg = 0;
  515.                             else if (thearg > emdp->lastrow)
  516.                                 /* keep within bottom margin */
  517.                                 thearg = emdp->lastrow;
  518.                         }    
  519.                         ypos = thearg;
  520.                         
  521.                         /* now set the x position */
  522.                         thearg = emdp->argarr[1];
  523.                         if (thearg)
  524.                             --thearg;
  525.                         if (thearg >= linelength) {
  526.                             thearg = lastcol; 
  527.                         }
  528.                         xpos = thearg;
  529.                         charp = emdp->charr + (ypos * linelength) + xpos;
  530.                         break;
  531.                     }
  532.                     case 'J': { 
  533.                         /* erase screen */
  534.                         if (emdp->wrapped)
  535.                             wrapdown();
  536.                         switch (thearg) {
  537.                             case 0: { 
  538.                                 /* clear to end of screen */
  539.                                 if (emdp->selrectvis || bkrd_act || emupdwait) {
  540.                                     /* must redraw through upd  */
  541.                                     for (count = ypos; count <= emdp->lastrow; count++)
  542.                                         modflg |= modmask[count];
  543.                                 }
  544.                                 else {
  545.                                     clr_eol();
  546.         
  547.                                     emdp->bigrect.top = (ypos + 1) * emdp->lineheight + emdp->voffset;
  548.                                     clearrect(&emdp->bigrect);
  549.                                     emdp->bigrect.top = emdp->voffset;
  550.                                     
  551.                                     /* set the line-cleared flag */
  552.                                     count = ypos;
  553.                                     if (xpos != 0)
  554.                                         count++;
  555.                                     for (; count <= emdp->lastrow; count++)
  556.                                         clrflg |= modmask[count];
  557.                                 }
  558.                                 /* blank out the screen map to the end of screen */
  559.                                 if (ypos == 0 && xpos == 0) {
  560.                                     /* save the screen before it gets overwritten */
  561.                                     if (!emdp->ibm_keymode)
  562.                                         savescreen();
  563.                                 }
  564.                                 /* TODO should saveline()s?
  565.                                 if (emdp->logerase)
  566.                                     saveline(charp, emdp->charrend - charp);
  567.                                  */
  568.                                 c19_blank(charp, emdp->charrend - charp);
  569.                                 break;
  570.                             }
  571.                             case 1: { 
  572.                                 /* clear screen up to & including cursor position */
  573.                                 Rect trect;
  574.                                 
  575.                                 if (emdp->selrectvis || bkrd_act || emupdwait) {
  576.                                     /* must redraw through upd  */
  577.                                     for (count = 0; count <= ypos; count++)
  578.                                         modflg |= modmask[count];
  579.                                 }
  580.                                 else {
  581.                                     emdp->bigrect.bottom = ypos * emdp->lineheight;
  582.                                     clearrect(&emdp->bigrect);
  583.                                     emdp->bigrect.bottom = emdp->bottommarg;
  584.                                     
  585.                                     trect.top = ypos * emdp->lineheight + emdp->voffset;
  586.                                     trect.left = emdp->hoffset;
  587.                                     trect.bottom = trect.top + emdp->lineheight;
  588.                                     trect.right = ((xpos + 1) * fontwidth) + emdp->hoffset;
  589.                                     clearrect(&trect);
  590.  
  591.                                     /* set the line-cleared flag */
  592.                                     for (count = 0; count < ypos; count++)
  593.                                         clrflg |= modmask[count];
  594.                                     if (xpos == lastcol)
  595.                                         /* last line was completely cleared also */
  596.                                         clrflg |= modmask[count];
  597.                                 }
  598.                                 if (ypos == emdp->lastrow && xpos == lastcol) {
  599.                                     /* save the screen before it gets overwritten */
  600.                                     if (!emdp->ibm_keymode)
  601.                                         savescreen();
  602.                                 }
  603.                                 /* 
  604.                                 else if (emdp->logerase)
  605.                                     saveline(charp, emdp->charrend - charp);
  606.                                 */
  607.                                 c19_blank(&emdp->charr[0], charp - emdp->charr + 1);
  608.                                 break;
  609.                             }
  610.                             case 2: { 
  611.                                 /* reset:  clear screen */
  612.                                 attrib &= NOATTR;
  613.                                 if (emdp->selrectvis || bkrd_act || emupdwait) {
  614.                                     /* TODO should have selerase()  */
  615.                                     modflg = SCRALLMOD;
  616.                                 }
  617.                                 else {
  618.                                     clearrect(&emdp->bigrect);
  619.                                     clrflg = SCRALLMOD;
  620.                                 }
  621. #ifdef FASTDRAW
  622.                                 setascattr_ds(attrib, emdp->inselection);
  623. #endif
  624.                                 if (!emdp->ibm_keymode)
  625.                                     savescreen();
  626.                                     /* save the screen before it gets overwritten */
  627.                         
  628.                                 /* blank out the screen map */
  629.                                 c19_blankmap(&emdp->charr[0]);
  630.                                 break;
  631.                             }
  632.                         }
  633.                         break;
  634.                     }
  635.                     case 'K': { 
  636.                         /* erase line */
  637.                         if (emdp->wrapped)
  638.                             wrapdown();
  639.                         switch (thearg) {
  640.                             case 0: {
  641.                                 clr_eol();
  642.                                 break;
  643.                             }
  644.                             case 1: {
  645.                                 clrtocurs();
  646.                                 break;
  647.                             }
  648.                             case 2: { 
  649.                                 /* clear current line */
  650.                                 Rect temprect;
  651.                                 char * destp;
  652.                                 
  653. #ifdef FASTDRAW                                
  654.                                 if (emdp->selrectvis || bkrd_act || emupdwait) {
  655.                                     /* must redraw through upd  */
  656.                                     modflg |= modmask[ypos];
  657.                                 }
  658.                                 else {
  659.                                     temprect.top = ypos * emdp->lineheight + emdp->voffset;
  660.                                     temprect.left = emdp->hoffset;
  661.                                     temprect.bottom = temprect.top + emdp->lineheight;
  662.                                     temprect.right = emdp->rightmarg;
  663.                                     clearrect(&temprect);
  664.  
  665.                                     clrflg |= modmask[ypos];
  666.                                 }
  667. #else
  668.                                 modflg |= modmask[ypos];
  669. #endif
  670.                                 destp = emdp->charr + ypos * linelength;
  671.                                 if (!emdp->ibm_keymode)
  672.                                     saveline(destp, linelength);
  673.                                         /* save the line if needed before it gets overwritten */
  674.                                 c19_blank(destp, linelength);
  675.                                 break;
  676.                             }
  677.                         }
  678.                         break;
  679.                     }
  680.                     case 'L': {
  681.                         /* insert line */
  682.                         if (emdp->wrapped)
  683.                             wrapdown();
  684.                         if (thearg == 0)
  685.                             thearg = 1;
  686.                         while (thearg--)
  687.                             ins_lin(ypos);
  688.                         charp -= xpos;
  689.                         xpos = 0;
  690.                         break;
  691.                     }
  692.                     case 'M': {
  693.                         /* delete line */
  694.                         if (emdp->wrapped)
  695.                             wrapdown();
  696.                         if (thearg == 0)
  697.                             thearg = 1;
  698.                         while (thearg--)
  699.                             del_lin(ypos);
  700.                         charp -= xpos;
  701.                         xpos = 0;
  702.                         break;
  703.                     }
  704.                     case 'P': {
  705.                         /* delete char */
  706.                         if (emdp->wrapped)
  707.                             wrapdown();
  708.                         if (thearg == 0)
  709.                             thearg = 1;
  710.                         while (thearg--)
  711.                             del_char();
  712.                         break;
  713.                     }
  714.                     case '@': {
  715.                         /* insert char */
  716.                         if (emdp->wrapped)
  717.                             wrapdown();
  718.                         if (thearg == 0)
  719.                             thearg = 1;
  720.                         while (thearg--)
  721.                             ins_char();
  722.                         break;
  723.                     }
  724.                     /* vt220 stuff not here:
  725.                         'X' erase n chars
  726.                         ?K selective erase in line
  727.                         ?J selective erase in display
  728.                         
  729.                         CSI?5 i auto print when cursor moves off line w/ LF, tab, w
  730.                         CSI?4 i auto print off
  731.                         CSI 5 i print without display
  732.                         CSI 4 i turn off print without display
  733.                         CSI ? 1 i print display line w/ cursor
  734.                         CSI i   print screen
  735.                         CSI 0 i ditto
  736.                         
  737.                     */
  738.                     case 'i': { 
  739.                         /* print screen without a dialog */
  740.                         if ((thearg == 0)) {
  741.                             QDprinttext(RF_PRINTSCREEN, FALSE);
  742.                         }
  743.                         break;
  744.                     }
  745.                     case 'c': { 
  746.                         /* whoami */
  747.                         if ((thearg == 0)) {
  748.                             if (emdp->disableterm[emdp->termtype]) {
  749.                                 /* hey, we're not currently identified! 
  750.                                     This happens w/ VAX/Wollongong TCP... */
  751.                                 if (!emdp->disableterm[TERM_VT100]) {
  752.                                     (*emdp->sendstr)(vt100AVOid);
  753.                                 }
  754.                                 else if (!emdp->disableterm[TERM_VT102]) {
  755.                                     (*emdp->sendstr)(vt102id);
  756.                                 }
  757.                                 else if (!emdp->disableterm[TERM_VT220]) {
  758.                                     (*emdp->sendstr)(vt220id);
  759.                                 }
  760.                                 else {
  761.                                     /* assume we're a VT100 */
  762.                                     (*emdp->sendstr)(vt100AVOid);
  763.                                 }
  764.                             }
  765.                             else {
  766.                                 switch (emdp->termtype) {
  767.                                     case TERM_VT100:
  768.                                         (*emdp->sendstr)(vt100AVOid);
  769.                                         break;
  770.                                     case TERM_VT102:
  771.                                         (*emdp->sendstr)(vt102id);
  772.                                         break;
  773.                                     case TERM_VT220:
  774.                                         (*emdp->sendstr)(vt220id);
  775.                                         break;
  776.                                 }
  777.                             }
  778.                         }
  779.                         break;
  780.                     }
  781.                     case 'h': {
  782.                         /* set ANSI modes */
  783.                         if (thearg == 4) {
  784.                             /* insert mode */
  785.                             inserton = TRUE;
  786.                         }
  787.                         else if (thearg == 20)
  788.                             /* CR = CR-LF mode */
  789.                             emdp->vtnewline = TRUE;
  790.                         break;
  791.                     }
  792.                     case 'l': {
  793.                         /* reset ANSI modes */
  794.                         if (thearg == 4) {
  795.                             /* insert mode */
  796.                             inserton = FALSE;
  797.                         }
  798.                         else if (thearg == 20) {
  799.                             /* CR = CR-LF mode */
  800.                             emdp->vtnewline = FALSE;
  801.                         }
  802.                         break;
  803.                     }
  804.                     case 'm': { 
  805.                         /* set attributes */
  806.                         for (index = 0; index < emdp->argcount; index++) {
  807.                             switch(emdp->argarr[index]) {
  808.                                 case 0: {
  809.                                     /* attributes off */
  810.                                     attrib &= NOATTR;
  811.                                     break;
  812.                                 }
  813.                                 case 1: {
  814.                                     /* bold */
  815.                                     attrib |= BOLD;
  816.                                     break;
  817.                                 }
  818.                                 case 4: {
  819.                                     /* underscore */
  820.                                     attrib |= UNDERSCORE;
  821.                                     break;
  822.                                 }
  823.                                 case 5: {
  824.                                     /* blink video */
  825.                                     attrib |= BLINK;
  826.                                     break;
  827.                                 }
  828.                                 case 7: {
  829.                                     /* reverse video */
  830.                                     attrib |= REVERSE;
  831.                                     break;
  832.                                 }
  833.                                 /* vt220 compatibility */
  834.                                 case 22: {
  835.                                     /* bold */
  836.                                     attrib &= ~BOLD;
  837.                                     break;
  838.                                 }
  839.                                 case 24: {
  840.                                     /* underscore */
  841.                                     attrib &= ~UNDERSCORE;
  842.                                     break;
  843.                                 }
  844.                                 case 25: {
  845.                                     /* blink video */
  846.                                     attrib &= ~BLINK;
  847.                                     break;
  848.                                 }
  849.                                 case 27: {
  850.                                     /* reverse video */
  851.                                     attrib &= ~REVERSE;
  852.                                     break;
  853.                                 }
  854.                             }
  855.                         }
  856. #ifdef FASTDRAW
  857.                         if (emdp->dsdraw)
  858.                             setascattr_ds(attrib, emdp->inselection);
  859. #endif
  860.                         break;
  861.                     }
  862.                     case 'n': { 
  863.                         char cursorstr[16];
  864.                         
  865.                         if (thearg == 5) {
  866.                             /* whoami */
  867.                             (*emdp->sendstr)(imokstr);
  868.                         }
  869.                         else if (thearg == 6) {
  870.                             /* report cursor position */
  871.                             int nypos;
  872.                             
  873.                             if (emdp->decom)
  874.                                 nypos = ypos - emdp->scrolltop;
  875.                             else
  876.                                 nypos = ypos;
  877.                             
  878.                             sprintf(cursorstr, "\033[%d;%dR", (int) ++nypos, (int) xpos + 1);
  879.                             (*emdp->sendstr)(cursorstr);
  880.                         }
  881.                         break;
  882.                     }
  883.                     case 'q': { 
  884.                         /* programmable LEDS 0 = reset */
  885.                         break;
  886.                     }
  887.                     case 'r': { 
  888.                         /* set scrolling region */
  889.                         
  890.                         if (emdp->wrapped)
  891.                             wrapdown();
  892.  
  893.                         if (emdp->argarr[0])
  894.                             --emdp->argarr[0];
  895.                         
  896.                         if (emdp->argarr[1])
  897.                             --emdp->argarr[1];
  898.                         else
  899.                             emdp->argarr[1] = emdp->lastrow;
  900.                         
  901.                         if (emdp->argarr[1] > emdp->lastrow
  902.                             || emdp->argarr[1] <= emdp->argarr[0])
  903.                             /* bad arguments */
  904.                             break;
  905.                             
  906.                         emdp->scrolltop = emdp->argarr[0];
  907.                         emdp->scrollbottom = emdp->argarr[1];
  908.                         emdp->scrollrect.top = emdp->scrolltop * emdp->lineheight + emdp->voffset;
  909.                         emdp->scrollrect.bottom = (emdp->scrollbottom + 1) * emdp->lineheight + emdp->voffset;
  910.                         
  911.                         xpos = 0;
  912.                         if (emdp->decom) {
  913.                             ypos = emdp->scrolltop;
  914.                             charp = emdp->charr + (emdp->scrolltop * linelength);
  915.                         }
  916.                         else {
  917.                             ypos = 0;
  918.                             charp = emdp->charr;
  919.                         }
  920.                         break;
  921.                     }
  922.                     case 'x': {
  923.                         /* request terminal parameters, report */
  924.                         (*emdp->sendstr)("\033[");
  925.                         if (thearg == 0)
  926.                             (*emdp->sendchar)('2');
  927.                         else
  928.                             (*emdp->sendchar)('3');
  929.                         (*emdp->sendstr)(";1;1;0;1;0x");
  930.                             /* report; no parity; 8 bits; 50 baud (limit nulls!); clkmul; junk; x */
  931.                         break;
  932.                     }
  933.                     case 'y': {
  934.                         /* confidence test; reset if second arg == 0 */
  935.                         if (emdp->argcount == 2 
  936.                             && emdp->argarr[0] == 2 
  937.                             && emdp->argarr[1] == 0)
  938.                             vt100reset();
  939.                         break;
  940.                     }
  941.                 }
  942. #ifdef TESTBOUND
  943.                 testbound();
  944. #endif
  945.  
  946.                 break;
  947.             }
  948.             case VT_QMARK: {
  949.                 int    index;
  950.     
  951.                 if (thechar < ' ') {
  952.                     /* an ASCII control char which needs to be interpreted */
  953.                     vtcontrol(thechar);
  954.                     break;
  955.                 }
  956.                 if ((thechar <= '9') && (thechar >= '0')) {
  957.                     *argp = (*argp * 10) + (thechar - '0');
  958.                     break;
  959.                 }
  960.                 if (thechar == ';') {
  961.                     if (emdp->argcount < MAXARGS) {
  962.                         argp++;
  963.                         emdp->argcount++;
  964.                     }
  965.                     break;
  966.                 }
  967.                 emdp->argcount++;
  968.                 vtmode = NORMMODE;
  969.                 if (thechar == 'h') {
  970.                     /* set DEC private mode mode on */
  971.                     
  972.                     /*     unimplemented:
  973.                         3 = column mode (80/132) columns 
  974.                         5 = screen mode (reverse)
  975.                         8 auto repeat
  976.                         9 = interlace
  977.                     */
  978.                     for (index = 0; index < emdp->argcount; index++) {
  979.                         switch (emdp->argarr[index]) {
  980.                             case 1: {
  981.                                 /* DECCKM cursor key mode */
  982.                                 if (!emdp->vtkeypad)
  983.                                     emdp->vtaltcursor = 'O';
  984.                                 break;
  985.                             }
  986.                             case 2: {
  987.                                 /* ANSI mode */
  988.                                 break;
  989.                             }
  990.                             case 3: {
  991.                                 /* DECCOLM 80 columns */
  992.                                 emdp->linelength = 132;
  993.                                 useqd(emdp);        
  994.                                     /* go into QuickDraw mode temporarily, since a
  995.                                         refresh might occur which would not be
  996.                                         supported by the useds() routines */
  997.                                 vt100reset();
  998.                                 setscreensize(emdp->fontsize);
  999.                                 break;
  1000.                             }
  1001.                             case 4: {
  1002.                                 /* jump scroll mode */
  1003. #ifdef VTJUMPSCROLL
  1004.                                 emdp->vtjumpscroll = FALSE;
  1005. #endif
  1006.                                 break;
  1007.                             }
  1008.                             case 6: {
  1009.                                 /* DEC origin mode */
  1010.                                 emdp->decom = TRUE;
  1011.                                 charp = emdp->charr + (emdp->scrolltop * linelength);
  1012.  
  1013.                                 ypos = emdp->scrolltop;
  1014.                                 xpos = 0;
  1015.                                 break;
  1016.                             }
  1017.                             case 7: { 
  1018.                                 /* auto wrap around */
  1019.                                 wrap_around = TRUE;
  1020.                                 break;
  1021.                             }
  1022.                         }
  1023.                     }
  1024.                 }
  1025.                 else if (thechar == 'l') {
  1026.                     /* reset mode */
  1027.                     for (index = 0; index < emdp->argcount; index++) {
  1028.                         switch (emdp->argarr[index]) {
  1029.                             case 1: {
  1030.                                 /* DECCKM cursor key mode */
  1031.                                 if (!emdp->vtkeypad)
  1032.                                     emdp->vtaltcursor = '[';
  1033.                                 break;
  1034.                             }
  1035.                             case 2: {
  1036.                                 /* VT52 mode */
  1037.                                 mode = NORMMODE;
  1038.                                 emdp->em = h19;
  1039.                                 emdp->emstr = h19str;
  1040.                                 emend();    /* emprep will be called again */
  1041.                                 h19str(strp, endp - strp);
  1042.                                     /* hand over remaining data */
  1043.                                 return(0);
  1044.                                 break;
  1045.                             }
  1046.                             case 3: {
  1047.                                 /* DECCOLM 80 columns */
  1048.                                 emdp->linelength = 80;
  1049.                                 useqd(emdp);        
  1050.                                 vt100reset();
  1051.                                 setscreensize(emdp->fontsize);
  1052.                                 break;
  1053.                             }
  1054.                             case 4: {
  1055.                                 /* DECSCLM scroll mode */
  1056. #ifdef VTJUMPSCROLL
  1057.                                 /* slows down scrolling too much */
  1058.                                 emdp->vtjumpscroll = TRUE;
  1059. #endif
  1060.                                 break;
  1061.                             }
  1062.                             case 6: {
  1063.                                 /* DEC origin mode */
  1064.                                 emdp->decom = FALSE;
  1065.                                 charp = emdp->charr;
  1066.                                 ypos = 0;
  1067.                                 xpos = 0;
  1068.                                 break;
  1069.                             }
  1070.                             case 7: { 
  1071.                                 wrap_around = FALSE;
  1072.                                 break;
  1073.                             }
  1074.                         }
  1075.                     }
  1076.                 }
  1077. #ifdef TESTBOUND
  1078.                 testbound();
  1079. #endif
  1080.                 break;
  1081.             }
  1082.             case VT_POUND: {
  1083.                 /* DEC double-width, double-height, test, etc. */
  1084.                 if (thechar == '8') {
  1085.                     /* DECALN alignment feature: fill screen with E's */
  1086.                     decaln();
  1087.                 }
  1088.                 vtmode = NORMMODE;
  1089.                 break;
  1090.             }
  1091.             case VT_LPAREN: {
  1092.                 if (thechar == '0') {
  1093.                     /* use vt graphic characters */
  1094.                     emdp->charsetG0 = VTFONT;
  1095.                 }
  1096.                 else {
  1097.                     /* return to norm font */
  1098.                     emdp->charsetG0 = NORMFONT;
  1099.                 }
  1100.                 if (!emdp->charsetSO) {
  1101.                     vtcharshift(FALSE);
  1102.                 }
  1103.                 vtmode = NORMMODE;
  1104.                 break;
  1105.             }
  1106.             case VT_RPAREN: {
  1107.                 if (thechar == '0') {
  1108.                     /* use vt graphic characters */
  1109.                     emdp->charsetG1 = VTFONT;
  1110.                 }
  1111.                 else {
  1112.                     /* return to norm font */
  1113.                     emdp->charsetG1 = NORMFONT;
  1114.                 }
  1115.                 if (emdp->charsetSO) {
  1116.                     vtcharshift(TRUE);
  1117.                 }
  1118.                 vtmode = NORMMODE;
  1119.                 break;
  1120.             }
  1121.             case VT_SPACE: {
  1122.                 /* 'F' is 7-bit control mode, 'G' is 8-bit (CSI) mode
  1123.                     so the terminal doesn't send <ESC>[
  1124.                     so just throw the next character out */
  1125.                 vtmode = NORMMODE;
  1126.                 break;
  1127.             }
  1128.             case CFTMODE: {
  1129.                 cft(thechar);
  1130.                 break;
  1131.             }
  1132.             case CFT2MODE: {
  1133.                 cft2(thechar);
  1134.                 break;
  1135.             }
  1136.             case C19FTMODE: {
  1137.                 c19ft(thechar);
  1138.                 break;
  1139.             }
  1140.             default: {
  1141.                 vtmode = NORMMODE;
  1142.                 break;
  1143.             }
  1144.         }
  1145.         /* continue character loop */
  1146.     }
  1147.     newcursor();
  1148.     emend();
  1149. }
  1150.  
  1151.  
  1152. /* make the emulator a vt100 */
  1153.  
  1154. vtinit()
  1155. {
  1156.     short count;
  1157.     short tab = 8;            /* first tab location */
  1158.     
  1159.     emdp->mode = VT100MODE;
  1160.     emdp->vtmode = NORMMODE;
  1161.     
  1162.     for (count = linelength / 8; --count > 0; tab += 8) {
  1163.         /* set tab stops */
  1164.         emdp->tabset[tab] = TRUE;
  1165.     }
  1166.     emdp->vtaltcursor = 'O';
  1167.     emdp->vtaltkeypad = FALSE;
  1168.     
  1169.     /* set keypad to user preference if requested */
  1170.     switch (emdp->vtkeypad) {
  1171.         case KEYPAD1: {
  1172.             /* user wants calculator */
  1173.             emdp->vtaltkeypad = FALSE;
  1174.             break;
  1175.         }
  1176.         case KEYPAD2: {
  1177.             /* user wants application */
  1178.             emdp->vtaltkeypad = TRUE;
  1179.             break;
  1180.         }
  1181.         case KEYPAD3: {
  1182.             /* user wants application alternate */
  1183.             emdp->vtaltkeypad = TRUE;
  1184.             emdp->vtaltcursor = '[';
  1185.             break;
  1186.         }
  1187.     }
  1188.  
  1189.     emdp->scrollrect.bottom = emdp->bottommarg;
  1190.     emdp->scrollrect.right = emdp->rightmarg;
  1191.  
  1192.     emdp->decom = FALSE;    
  1193.     emdp->vtnewline = FALSE;
  1194.     emdp->wrapped = FALSE;
  1195.  
  1196.     /* character set state */
  1197.     emdp->charsetSO = FALSE;                        /* G0 set shifted out? */
  1198.     emdp->charsetG0 = NORMFONT;                /* G0 character set */
  1199.     emdp->charsetG1 = NORMFONT;                /* G1 character set */
  1200.     emdp->charset = 0;
  1201.  
  1202.     /* reset scrolling region */
  1203.     emdp->scrolltop = TOPROW;
  1204.     emdp->scrollbottom = emdp->lastrow;
  1205.     emdp->scrollrect.top = emdp->voffset;
  1206.     emdp->scrollrect.left = emdp->hoffset;
  1207.     emdp->scrollrect.bottom = emdp->bottommarg;
  1208.     emdp->scrollrect.right = emdp->rightmarg;
  1209. }
  1210.  
  1211.  
  1212. /* reset the state of the vt100 */
  1213.  
  1214. vt100reset()
  1215. {
  1216.     short count;
  1217.     
  1218.     h19reset();                    /* reset the "vt52" also */
  1219.  
  1220.     for (count = 0; count < linelength; ) {
  1221.         /* clear all tabs */
  1222.         emdp->tabset[count++] = FALSE;
  1223.     }
  1224.     while (emdp->argcount)
  1225.         /* clear the old entries */
  1226.         emdp->argarr[emdp->argcount--] = 0;
  1227.     emdp->argp = &emdp->argarr[0];
  1228.  
  1229.     vtinit();
  1230.  
  1231.     emdp->mode = VT100MODE;
  1232.     setcontext(emdp);                    /* update globals */
  1233. }
  1234.  
  1235.  
  1236. testbound()
  1237. {
  1238.     if (xpos < 0 || xpos > linelength 
  1239.         || ypos < 0 || ypos > emdp->lastrow
  1240.         || charp < emdp->charr || charp >= emdp->charrend)
  1241.         badbound();
  1242. }
  1243.  
  1244.  
  1245. /* a label on which to set a breakpoint */
  1246.  
  1247. badbound()
  1248. {
  1249. }
  1250.  
  1251. /* a close duplicate of the switch in the NORMMODE state */
  1252.  
  1253. vtcontrol(thechar)
  1254. register unsigned char thechar;
  1255. {
  1256.     switch (thechar) {
  1257.         case 0x07: {
  1258.             /* BELL */
  1259.             if (!emdp->emdisable)
  1260.                 beep();
  1261.             break;
  1262.         }
  1263.         case 0x08: {
  1264.             /* BS */
  1265.             if (emdp->wrapped)
  1266.                 wrapdown();
  1267.             if (xpos > 0) {
  1268.                 --xpos;
  1269.                 --charp;
  1270.             }
  1271.             break;
  1272.         }
  1273.         case 0x09: {
  1274.             /* HTAB */
  1275.             vttab();
  1276.             break;
  1277.         }
  1278.         case 0x0d: {
  1279.             /* CR */
  1280.             charp -= xpos;
  1281.             xpos = 0;
  1282.             emdp->wrapped = FALSE;
  1283.             break;
  1284.         }
  1285.         case 0x0a:
  1286.         case 0x0b:
  1287.         case 0x0c: {
  1288.             /* LF, VT, & FF */
  1289.             if (emdp->vtnewline) {
  1290.                 /* do a CR if in newline mode */
  1291.                 charp -= xpos;
  1292.                 xpos = 0;
  1293.                 emdp->wrapped = FALSE;
  1294.             }
  1295.             if (emdp->wrapped) {
  1296.                 wrapdown();
  1297.             }
  1298.             else {
  1299.                 if (ypos < emdp->scrollbottom) {
  1300.                     charp += linelength;
  1301.                     ypos++;
  1302.                 }
  1303.                 else {
  1304.                     if (emdp->scrolltop == TOPROW && emdp->scrollbottom == emdp->lastrow) {
  1305.                         (*emdp->scrollup)();
  1306.                     }
  1307.                     else
  1308.                         del_lin(emdp->scrolltop);
  1309.                 }
  1310.             }
  1311.             break;
  1312.         }
  1313.         case 0x0e: {
  1314.             /* SO, shift out G0 character set (select G1) */
  1315.             vtcharshift(TRUE);
  1316.             break;
  1317.         }
  1318.         case 0x0f: {
  1319.             /* SI, shift in G0 character set */
  1320.             vtcharshift(FALSE);
  1321.             break;
  1322.         }
  1323.         case 0x1b: {
  1324.             /* ESC--do nothing in this mode */
  1325.             break;
  1326.         }
  1327.         case 24:
  1328.         case 26: {
  1329.             /* CAN / SUB cancel current escape sequence */
  1330.             vtmode = NORMMODE;
  1331.             break;
  1332.         }
  1333.         case X_OFF: {
  1334.             break;
  1335.         }
  1336.         case X_ON: {
  1337.             break;
  1338.         }
  1339.     }
  1340. }
  1341.  
  1342.  
  1343. /* fill the screen with E's to help "align the screen"--heh, heh... */
  1344.  
  1345. decaln()
  1346. {
  1347.     register char * thep = &emdp->charr[0];
  1348.     
  1349.     modflg = SCRALLMOD;
  1350.     while (thep < emdp->charrend) {
  1351.         *thep++ = 'E';
  1352.     }
  1353. }                    
  1354.  
  1355.  
  1356. /* the cursor was at the end of line in the would-wrap state */
  1357.  
  1358. wrapdown()
  1359. {
  1360.     emdp->wrapped = FALSE;
  1361.     charp -= xpos;
  1362.     xpos = 0;
  1363.     if (ypos < emdp->scrollbottom) {
  1364.         charp += linelength;
  1365.         ypos++;
  1366.     }
  1367.     else {
  1368.         if (emdp->scrolltop == TOPROW && emdp->scrollbottom == emdp->lastrow) {
  1369.             (*emdp->scrollup)();
  1370.         }
  1371.         else
  1372.             del_lin(emdp->scrolltop);
  1373.     }
  1374. }
  1375.  
  1376.  
  1377.  
  1378. vtcharshift(state)
  1379. int state;
  1380. {
  1381.     emdp->charsetSO = state;
  1382.     if (state)
  1383.         emdp->charset = emdp->charsetG1;
  1384.     else
  1385.         emdp->charset = emdp->charsetG0;
  1386.  
  1387. #ifndef MERGEDVTCHARS
  1388.     /* separate attribute not needed if character sets merged... */
  1389.     attrib &= VTATTR;
  1390.     attrib |= emdp->charset;
  1391.  
  1392. #ifdef FASTDRAW
  1393.     setascattr_ds(attrib, emdp->inselection);
  1394. #endif
  1395.  
  1396. #endif
  1397. }
  1398.  
  1399.  
  1400.  
  1401. vttab()
  1402. {
  1403.     short shift;
  1404.  
  1405.     if (emdp->wrapped)
  1406.         wrapdown();
  1407.  
  1408.     /* go to next tab */
  1409.     for (shift = xpos; ++shift < linelength;) {
  1410.         if (emdp->tabset[shift]) {
  1411.             charp += shift - xpos;
  1412.             xpos = shift;
  1413.             break;
  1414.         }
  1415.     }
  1416.     /* no tab, go to end of line */
  1417.     if (shift == linelength) {
  1418.         charp += linelength - 1 - xpos;
  1419.         xpos = linelength - 1;
  1420.     }
  1421. }